import urllib2
import os
import time
import re
import random
import tempfile

ip_hosts = [
        'http://ipid.shat.net/iponly/',
        'http://www.vidalia-project.net/iptest/ip.php',
        'http://www.alexnolan.net/ip/',
        'http://whatismyip.org',
        'http://www.freehaven.net/~edmanm/ip.php',
        'http://myip.dk'
        ]

def getip(verbose=False):
    """
    Get the external ip address as seen from http://whatismyip.org/ or similar
    site and cache the result in the home directory. Update it at most once per hour.
    """
    ip_cache = None
    if os.environ.has_key("HOME"):
        ip_cache = os.path.join(os.environ['HOME'],".ip_cache")
    else:
        ip_cache = os.path.join(tempfile.gettempdir(),".ip_cache."+str(os.getuid()))
    ip = None
    store = True

    if os.path.isfile(ip_cache):
        store = False
        st = os.stat(ip_cache)
        tdiff = time.time()-st[8]
        if tdiff > 3600.0 or st[4] != os.getuid():
            store = True
        fp = open(ip_cache,"r")
        text = fp.read()
        g=re.search(r'\b\d+\.\d+\.\d+\.\d+\b',text)
        if g:
            ip = g.group(0)
        else:
            store = True
        fp.close()

    if store:
        # Don't always use the same ip host, distribute the load
        random.shuffle(ip_hosts)
        for ip_host in ip_hosts:
            text = ""
            if verbose:
                print "trying",ip_host
            try:
                text = urllib2.urlopen(ip_host).read()
            except:
                continue
            g=re.search(r'\b\d+\.\d+\.\d+\.\d+\b',text)
            if g:
                ip = g.group(0)
                try:
                    fp = open(ip_cache,"w")
                    fp.writelines([ip])
                    fp.close()
                except:
                    if verbose:
                        print "Could not write "+ip_cache
                break
            elif verbose:
                print 'parse failed: ',text
    return ip


if __name__ == '__main__':
    print getip(verbose=True)
